/*
 * Copyright (c) 2017.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.mybatis.generator.plugins;

import com.itfsw.mybatis.generator.plugins.utils.FormatTools;
import com.itfsw.mybatis.generator.plugins.utils.JavaElementGeneratorTools;
import com.itfsw.mybatis.generator.plugins.utils.XmlElementGeneratorTools;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.*;
import org.mybatis.generator.codegen.mybatis3.ListUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * selectByPrimaryKeys插件
 * create by hedong 2020/7/9
 */
public class SelectByPrimaryKeysPlugin extends PluginAdapter {

     private static final Logger LOGGER = LoggerFactory.getLogger(SelectByPrimaryKeysPlugin.class);

    public static final String METHOD_SELECT_BY_PRIMARY_KEYS = "selectByPrimaryKeys";  // 方法名

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }


    /**
     * Java Client Methods 生成
     * 具体执行顺序 http://www.mybatis.org/generator/reference/pluggingIn.html
     *
     * @param interfaze
     * @param topLevelClass
     * @param introspectedTable
     * @return
     */
    @Override
    public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        String selectByPrimaryKeys = introspectedTable.getTableConfiguration().getProperty(METHOD_SELECT_BY_PRIMARY_KEYS);
        if ("false".equals(selectByPrimaryKeys)) {
            return true;
        }
        // 没有主键 就不生成直接返回
        List<IntrospectedColumn> primaryKeyColumns = introspectedTable.getPrimaryKeyColumns();
        if(primaryKeyColumns == null || primaryKeyColumns.size() ==0){
            return true;
        }

        // 参数类型
        IntrospectedColumn  primaryKeyColumn = primaryKeyColumns.get(0);
        FullyQualifiedJavaType paramType = FullyQualifiedJavaType.getNewListInstance();
        paramType.addTypeArgument(primaryKeyColumn.getFullyQualifiedJavaType());
        // 返回值类型
        FullyQualifiedJavaType returnType = FullyQualifiedJavaType.getNewListInstance();
        returnType.addTypeArgument(introspectedTable.getRules().calculateAllFieldsClass());
        Method method = JavaElementGeneratorTools.generateMethod(
                METHOD_SELECT_BY_PRIMARY_KEYS,
                JavaVisibility.DEFAULT,
                returnType,
                new Parameter(paramType, primaryKeyColumn.getJavaProperty()+"s",String.format("@Param(\"%s\")", primaryKeyColumn.getJavaProperty()+"s"))
        );
        // interface 增加方法
        FormatTools.addMethodWithBestPosition(interfaze, method);
        LOGGER.debug("selectByPrimaryKeys插件:" + interfaze.getType().getShortName() + "增加selectByPrimaryKeys方法。");
        return true;
    }

    /**
     * SQL Map Methods 生成
     * 具体执行顺序 http://www.mybatis.org/generator/reference/pluggingIn.html
     *
     * @param document
     * @param introspectedTable
     * @return
     */
    @Override
    public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
        String selectByPrimaryKeys = introspectedTable.getTableConfiguration().getProperty(METHOD_SELECT_BY_PRIMARY_KEYS);
        if ("false".equals(selectByPrimaryKeys)) {
            return true;
        }
        // 没有主键 就不生成直接返回
        List<IntrospectedColumn> primaryKeyColumns = introspectedTable.getPrimaryKeyColumns();
        if(primaryKeyColumns == null || primaryKeyColumns.size() ==0){
            return true;
        }

        IntrospectedColumn primaryKeyColumn = primaryKeyColumns.get(0);

        //  selectByPrimaryKeys
        XmlElement selectByPrimaryKeysElement = new XmlElement("select");
        selectByPrimaryKeysElement.addAttribute(new Attribute("id", METHOD_SELECT_BY_PRIMARY_KEYS));
        // 参数类型
        selectByPrimaryKeysElement.addAttribute(new Attribute("parameterType", introspectedTable.getRules().calculateAllFieldsClass().getFullyQualifiedNameWithoutTypeParameters()));
        selectByPrimaryKeysElement.addAttribute(new Attribute("resultMap", "BaseResultMap"));

        selectByPrimaryKeysElement.addElement(new TextElement("select"));
        for (Element element : XmlElementGeneratorTools.generateKeys(ListUtilities.removeIdentityAndGeneratedAlwaysColumns(introspectedTable.getAllColumns()), false)) {
            selectByPrimaryKeysElement.addElement(element);
        }
        selectByPrimaryKeysElement.addElement(new TextElement("from " + introspectedTable.getFullyQualifiedTableNameAtRuntime()));
        selectByPrimaryKeysElement.addElement(new TextElement("where"));

        XmlElement foreachElement = new XmlElement("foreach ");
        foreachElement.addAttribute(new Attribute("collection",primaryKeyColumn.getJavaProperty()+"s"));
        foreachElement.addAttribute(new Attribute("item",primaryKeyColumn.getJavaProperty()));
        foreachElement.addAttribute(new Attribute("open",primaryKeyColumn.getActualColumnName() +" IN("));
        foreachElement.addAttribute(new Attribute("separator",","));
        foreachElement.addAttribute(new Attribute("close",")"));

        foreachElement.addElement(new TextElement(String.format("#{%s}", primaryKeyColumn.getJavaProperty())));
        selectByPrimaryKeysElement.addElement(foreachElement);
        document.getRootElement().addElement(selectByPrimaryKeysElement);
        LOGGER.debug("selectByPrimaryKeys插件:" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加selectByPrimaryKeys实现方法。");

        return true;
    }

}